#include "ScannerUI.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QHeaderView>
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QTextStream>
#include <QtGui/QFont>
#include <QtGui/QIcon>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <dlfcn.h>
#endif

// 静态成员初始化
ScannerUI* ScannerUI::instance = nullptr;

ScannerUI::ScannerUI(QWidget *parent)
    : QMainWindow(parent)
    , centralWidget(nullptr)
    , scannerDll(nullptr)
    , scanner(nullptr)
    , updateTimer(new QTimer(this))
    , totalFiles(0)
    , totalBytes(0)
    , isScanning(false)
{
    instance = this;
    
    setupUI();
    setupMenuBar();
    setupStatusBar();
    connectSignals();
    
    // 加载DLL并初始化
    if (loadScannerDLL()) {
        initializeScanner();
    } else {
        QMessageBox::critical(this, "错误", "无法加载文件扫描器DLL");
    }
    
    // 设置更新定时器
    updateTimer->setInterval(100); // 100ms更新一次
    connect(updateTimer, &QTimer::timeout, this, &ScannerUI::updateUI);
    
    enableControls(true);
}

ScannerUI::~ScannerUI() {
    if (updateTimer->isActive()) {
        updateTimer->stop();
    }
    
    cleanupScanner();
    unloadScannerDLL();
    
    instance = nullptr;
}

void ScannerUI::setupUI() {
    setWindowTitle("高效文件扫描器 v1.0");
    setMinimumSize(800, 600);
    resize(1200, 800);
    
    centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);
    
    mainLayout = new QVBoxLayout(centralWidget);
    mainSplitter = new QSplitter(Qt::Vertical, this);
    mainLayout->addWidget(mainSplitter);
    
    // 控制面板
    controlGroup = new QGroupBox("扫描控制", this);
    controlLayout = new QGridLayout(controlGroup);
    
    // 路径选择
    controlLayout->addWidget(new QLabel("扫描路径:"), 0, 0);
    pathEdit = new QLineEdit(this);
    pathEdit->setPlaceholderText("请选择要扫描的文件夹路径...");
    pathEdit->setText(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
    controlLayout->addWidget(pathEdit, 0, 1);
    
    browseButton = new QPushButton("浏览...", this);
    browseButton->setMaximumWidth(80);
    controlLayout->addWidget(browseButton, 0, 2);
    
    // 控制按钮
    QHBoxLayout* buttonLayout = new QHBoxLayout();
    startButton = new QPushButton("开始扫描", this);
    startButton->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }");
    stopButton = new QPushButton("停止扫描", this);
    stopButton->setStyleSheet("QPushButton { background-color: #f44336; color: white; font-weight: bold; }");
    stopButton->setEnabled(false);
    clearButton = new QPushButton("清空结果", this);
    exportButton = new QPushButton("导出结果", this);
    
    buttonLayout->addWidget(startButton);
    buttonLayout->addWidget(stopButton);
    buttonLayout->addWidget(clearButton);
    buttonLayout->addWidget(exportButton);
    buttonLayout->addStretch();
    
    controlLayout->addLayout(buttonLayout, 1, 0, 1, 3);
    
    // 进度显示面板
    progressGroup = new QGroupBox("扫描进度", this);
    progressLayout = new QVBoxLayout(progressGroup);
    
    progressBar = new QProgressBar(this);
    progressBar->setRange(0, 0); // 不确定进度
    progressBar->setVisible(false);
    progressLayout->addWidget(progressBar);
    
    statusLabel = new QLabel("就绪", this);
    statusLabel->setStyleSheet("QLabel { font-weight: bold; color: #2196F3; }");
    progressLayout->addWidget(statusLabel);
    
    filesCountLabel = new QLabel("文件数量: 0", this);
    totalSizeLabel = new QLabel("总大小: 0 B", this);
    currentFileLabel = new QLabel("当前文件: 无", this);
    currentFileLabel->setWordWrap(true);
    
    progressLayout->addWidget(filesCountLabel);
    progressLayout->addWidget(totalSizeLabel);
    progressLayout->addWidget(currentFileLabel);
    
    // 结果显示面板
    resultsGroup = new QGroupBox("扫描结果", this);
    resultsLayout = new QVBoxLayout(resultsGroup);
    
    QSplitter* resultsSplitter = new QSplitter(Qt::Horizontal, this);
    
    // 文件列表
    fileList = new QListWidget(this);
    fileList->setAlternatingRowColors(true);
    fileList->setSortingEnabled(true);
    resultsSplitter->addWidget(fileList);
    
    // 详细信息
    detailsText = new QTextEdit(this);
    detailsText->setReadOnly(true);
    detailsText->setMaximumWidth(300);
    detailsText->setPlainText("选择文件查看详细信息...");
    resultsSplitter->addWidget(detailsText);
    
    resultsSplitter->setSizes({600, 300});
    resultsLayout->addWidget(resultsSplitter);
    
    // 添加到主分割器
    QWidget* topWidget = new QWidget();
    QVBoxLayout* topLayout = new QVBoxLayout(topWidget);
    topLayout->addWidget(controlGroup);
    topLayout->addWidget(progressGroup);
    
    mainSplitter->addWidget(topWidget);
    mainSplitter->addWidget(resultsGroup);
    mainSplitter->setSizes({200, 400});
}

void ScannerUI::setupMenuBar() {
    menuBar = this->menuBar();
    
    QMenu* fileMenu = menuBar->addMenu("文件(&F)");
    
    exportButton->setShortcut(QKeySequence::Save);
    fileMenu->addAction(exportButton->text(), this, &ScannerUI::onExportResults, QKeySequence::Save);
    fileMenu->addSeparator();
    
    exitAction = new QAction("退出(&X)", this);
    exitAction->setShortcut(QKeySequence::Quit);
    connect(exitAction, &QAction::triggered, this, &QWidget::close);
    fileMenu->addAction(exitAction);
    
    QMenu* helpMenu = menuBar->addMenu("帮助(&H)");
    aboutAction = new QAction("关于(&A)", this);
    connect(aboutAction, &QAction::triggered, this, &ScannerUI::onAbout);
    helpMenu->addAction(aboutAction);
}

void ScannerUI::setupStatusBar() {
    statusBar = this->statusBar();
    statusBar->showMessage("就绪");
}

void ScannerUI::connectSignals() {
    connect(browseButton, &QPushButton::clicked, this, &ScannerUI::onBrowseFolder);
    connect(startButton, &QPushButton::clicked, this, &ScannerUI::onStartScan);
    connect(stopButton, &QPushButton::clicked, this, &ScannerUI::onStopScan);
    connect(clearButton, &QPushButton::clicked, this, &ScannerUI::onClearResults);
    connect(exportButton, &QPushButton::clicked, this, &ScannerUI::onExportResults);
    connect(fileList, &QListWidget::itemClicked, this, &ScannerUI::onFileItemClicked);
}

bool ScannerUI::loadScannerDLL() {
#ifdef _WIN32
    scannerDll = LoadLibraryA("FileScanner.dll");
    if (!scannerDll) {
        return false;
    }
    
    createScannerFunc = (CreateScannerFunc)GetProcAddress(scannerDll, "CreateScanner");
    destroyScannerFunc = (DestroyScannerFunc)GetProcAddress(scannerDll, "DestroyScanner");
    startScanFunc = (StartScanFunc)GetProcAddress(scannerDll, "StartScan");
    stopScanFunc = (StopScanFunc)GetProcAddress(scannerDll, "StopScan");
    isScanningFunc = (IsScanningFunc)GetProcAddress(scannerDll, "IsScanning");
    setProgressCallbackFunc = (SetProgressCallbackFunc)GetProcAddress(scannerDll, "SetProgressCallback");
    setCompleteCallbackFunc = (SetCompleteCallbackFunc)GetProcAddress(scannerDll, "SetCompleteCallback");
    getScanStatusFunc = (GetScanStatusFunc)GetProcAddress(scannerDll, "GetScanStatus");
    getTotalFilesScannedFunc = (GetTotalFilesScannedFunc)GetProcAddress(scannerDll, "GetTotalFilesScanned");
    getTotalBytesScannedFunc = (GetTotalBytesScannedFunc)GetProcAddress(scannerDll, "GetTotalBytesScanned");
#else
    scannerDll = dlopen("./libFileScanner.so", RTLD_LAZY);
    if (!scannerDll) {
        return false;
    }
    
    createScannerFunc = (CreateScannerFunc)dlsym(scannerDll, "CreateScanner");
    destroyScannerFunc = (DestroyScannerFunc)dlsym(scannerDll, "DestroyScanner");
    startScanFunc = (StartScanFunc)dlsym(scannerDll, "StartScan");
    stopScanFunc = (StopScanFunc)dlsym(scannerDll, "StopScan");
    isScanningFunc = (IsScanningFunc)dlsym(scannerDll, "IsScanning");
    setProgressCallbackFunc = (SetProgressCallbackFunc)dlsym(scannerDll, "SetProgressCallback");
    setCompleteCallbackFunc = (SetCompleteCallbackFunc)dlsym(scannerDll, "SetCompleteCallback");
    getScanStatusFunc = (GetScanStatusFunc)dlsym(scannerDll, "GetScanStatus");
    getTotalFilesScannedFunc = (GetTotalFilesScannedFunc)dlsym(scannerDll, "GetTotalFilesScanned");
    getTotalBytesScannedFunc = (GetTotalBytesScannedFunc)dlsym(scannerDll, "GetTotalBytesScanned");
#endif
    
    return createScannerFunc && destroyScannerFunc && startScanFunc && 
           stopScanFunc && isScanningFunc && setProgressCallbackFunc && 
           setCompleteCallbackFunc && getScanStatusFunc && 
           getTotalFilesScannedFunc && getTotalBytesScannedFunc;
}

void ScannerUI::unloadScannerDLL() {
    if (scannerDll) {
#ifdef _WIN32
        FreeLibrary(scannerDll);
#else
        dlclose(scannerDll);
#endif
        scannerDll = nullptr;
    }
}

bool ScannerUI::initializeScanner() {
    if (!createScannerFunc) {
        return false;
    }
    
    scanner = createScannerFunc();
    if (!scanner) {
        return false;
    }
    
    // 设置回调函数
    setProgressCallbackFunc(scanner, progressCallback);
    setCompleteCallbackFunc(scanner, completeCallback);
    
    return true;
}

void ScannerUI::cleanupScanner() {
    if (scanner && destroyScannerFunc) {
        destroyScannerFunc(scanner);
        scanner = nullptr;
    }
}

void ScannerUI::onBrowseFolder() {
    QString dir = QFileDialog::getExistingDirectory(this, "选择扫描文件夹", pathEdit->text());
    if (!dir.isEmpty()) {
        pathEdit->setText(dir);
    }
}

void ScannerUI::onStartScan() {
    QString path = pathEdit->text().trimmed();
    if (path.isEmpty()) {
        QMessageBox::warning(this, "警告", "请选择要扫描的文件夹路径");
        return;
    }
    
    QDir dir(path);
    if (!dir.exists()) {
        QMessageBox::warning(this, "警告", "指定的文件夹不存在");
        return;
    }
    
    if (!scanner || !startScanFunc) {
        QMessageBox::critical(this, "错误", "扫描器未初始化");
        return;
    }
    
    // 清空之前的结果
    onClearResults();
    
    // 开始扫描
    std::wstring wpath = path.toStdWString();
    if (startScanFunc(scanner, wpath.c_str())) {
        isScanning = true;
        enableControls(false);
        progressBar->setVisible(true);
        statusLabel->setText("正在扫描...");
        statusBar->showMessage("扫描进行中...");
        updateTimer->start();
    } else {
        QMessageBox::critical(this, "错误", "启动扫描失败");
    }
}

void ScannerUI::onStopScan() {
    if (scanner && stopScanFunc) {
        stopScanFunc(scanner);
        isScanning = false;
        enableControls(true);
        progressBar->setVisible(false);
        statusLabel->setText("扫描已停止");
        statusBar->showMessage("扫描已停止");
        updateTimer->stop();
    }
}

void ScannerUI::onClearResults() {
    QMutexLocker locker(&dataMutex);
    scanResults.clear();
    fileList->clear();
    detailsText->setPlainText("选择文件查看详细信息...");
    totalFiles = 0;
    totalBytes = 0;
    updateProgressInfo();
}

void ScannerUI::onExportResults() {
    if (scanResults.empty()) {
        QMessageBox::information(this, "提示", "没有扫描结果可导出");
        return;
    }
    
    QString fileName = QFileDialog::getSaveFileName(this, "导出扫描结果", 
        "scan_results.txt", "文本文件 (*.txt);;CSV文件 (*.csv)");
    
    if (fileName.isEmpty()) {
        return;
    }
    
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::critical(this, "错误", "无法创建导出文件");
        return;
    }
    
    QTextStream out(&file);
    out.setCodec("UTF-8");
    
    if (fileName.endsWith(".csv")) {
        out << "文件路径,文件大小(字节),文件大小\n";
        for (const auto& result : scanResults) {
            out << "\"" << result.filePath << "\"," 
                << result.fileSize << "," 
                << result.sizeString << "\n";
        }
    } else {
        out << "文件扫描结果报告\n";
        out << "===================\n";
        out << "总文件数: " << scanResults.size() << "\n";
        out << "总大小: " << formatFileSize(totalBytes) << "\n\n";
        
        for (const auto& result : scanResults) {
            out << result.filePath << " (" << result.sizeString << ")\n";
        }
    }
    
    QMessageBox::information(this, "成功", "扫描结果已导出到: " + fileName);
}

void ScannerUI::onAbout() {
    QMessageBox::about(this, "关于", 
        "高效文件扫描器 v1.0\n\n"
        "基于多线程技术的高性能文件扫描工具\n"
        "支持实时进度显示和结果导出\n\n"
        "技术特性:\n"
        "• 多线程并行扫描\n"
        "• 实时进度反馈\n"
        "• 可随时中断扫描\n"
        "• 跨平台支持\n\n"
        "开发: 亿图视觉面试题");
}

void ScannerUI::updateUI() {
    if (!scanner || !getTotalFilesScannedFunc || !getTotalBytesScannedFunc || !isScanningFunc) {
        return;
    }
    
    // 更新统计信息
    totalFiles = getTotalFilesScannedFunc(scanner);
    totalBytes = getTotalBytesScannedFunc(scanner);
    
    updateProgressInfo();
    
    // 检查扫描状态
    if (!isScanningFunc(scanner) && isScanning) {
        isScanning = false;
        enableControls(true);
        progressBar->setVisible(false);
        statusLabel->setText("扫描完成");
        statusBar->showMessage("扫描完成");
        updateTimer->stop();
    }
}

void ScannerUI::onFileItemClicked(QListWidgetItem* item) {
    if (!item) {
        return;
    }
    
    QString filePath = item->data(Qt::UserRole).toString();
    QString details = getFileDetails(filePath);
    detailsText->setPlainText(details);
}

void ScannerUI::updateProgressInfo() {
    filesCountLabel->setText(QString("文件数量: %1").arg(totalFiles));
    totalSizeLabel->setText(QString("总大小: %1").arg(formatFileSize(totalBytes)));
    
    QMutexLocker locker(&dataMutex);
    if (!currentScannedFile.isEmpty()) {
        currentFileLabel->setText(QString("当前文件: %1").arg(currentScannedFile));
    }
}

void ScannerUI::updateFileList() {
    QMutexLocker locker(&dataMutex);
    
    // 只添加新的文件项，避免重复刷新整个列表
    int currentCount = fileList->count();
    for (int i = currentCount; i < scanResults.size(); ++i) {
        const auto& result = scanResults[i];
        QListWidgetItem* item = new QListWidgetItem();
        item->setText(QString("%1 (%2)").arg(result.filePath, result.sizeString));
        item->setData(Qt::UserRole, result.filePath);
        item->setToolTip(result.filePath);
        fileList->addItem(item);
    }
}

void ScannerUI::enableControls(bool enabled) {
    pathEdit->setEnabled(enabled);
    browseButton->setEnabled(enabled);
    startButton->setEnabled(enabled);
    stopButton->setEnabled(!enabled);
    clearButton->setEnabled(enabled);
    exportButton->setEnabled(enabled && !scanResults.empty());
}

QString ScannerUI::formatFileSize(uint64_t bytes) {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    int unitIndex = 0;
    double size = static_cast<double>(bytes);
    
    while (size >= 1024.0 && unitIndex < 4) {
        size /= 1024.0;
        unitIndex++;
    }
    
    return QString("%1 %2").arg(size, 0, 'f', 2).arg(units[unitIndex]);
}

QString ScannerUI::getFileDetails(const QString& filePath) {
    QFileInfo fileInfo(filePath);
    
    QString details;
    details += "文件路径: " + filePath + "\n";
    details += "文件名: " + fileInfo.fileName() + "\n";
    details += "文件大小: " + formatFileSize(fileInfo.size()) + "\n";
    details += "创建时间: " + fileInfo.birthTime().toString("yyyy-MM-dd hh:mm:ss") + "\n";
    details += "修改时间: " + fileInfo.lastModified().toString("yyyy-MM-dd hh:mm:ss") + "\n";
    details += "访问时间: " + fileInfo.lastRead().toString("yyyy-MM-dd hh:mm:ss") + "\n";
    details += "文件类型: " + fileInfo.suffix().toUpper() + "\n";
    details += "是否可读: " + (fileInfo.isReadable() ? "是" : "否") + "\n";
    details += "是否可写: " + (fileInfo.isWritable() ? "是" : "否") + "\n";
    
    return details;
}

// 静态回调函数实现
void ScannerUI::progressCallback(const wchar_t* filePath, uint64_t fileSize, uint64_t totalFiles) {
    if (!instance) {
        return;
    }
    
    QString qFilePath = QString::fromWCharArray(filePath);
    
    QMutexLocker locker(&instance->dataMutex);
    instance->currentScannedFile = qFilePath;
    instance->scanResults.emplace_back(qFilePath, fileSize);
    
    // 在主线程中更新UI
    QMetaObject::invokeMethod(instance, "updateFileList", Qt::QueuedConnection);
}

void ScannerUI::completeCallback(const ScanResult* results, int count, int status) {
    if (!instance) {
        return;
    }
    
    // 扫描完成的处理在updateUI中进行
    Q_UNUSED(results)
    Q_UNUSED(count)
    Q_UNUSED(status)
}

// UIFileInfo的formatSize实现
void ScannerUI::UIFileInfo::formatSize() {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    int unitIndex = 0;
    double size = static_cast<double>(fileSize);
    
    while (size >= 1024.0 && unitIndex < 4) {
        size /= 1024.0;
        unitIndex++;
    }
    
    sizeString = QString("%1 %2").arg(size, 0, 'f', 2).arg(units[unitIndex]);
}